<?php

namespace CtyunOss\cors;

use CtyunOss\config\OssConfig;
use CtyunOss\config\Request;
use Symfony\Component\VarDumper\VarDumper;

/**
 * 天翼云数据签名V2
 * @package    CtyunOss\cors
 *
 * @author     Violet_Ice紫冰 <violetice@aliyun.com>
 * @create     2020-06-24 15:32:20
 */
class SignV2
{
    /** @var Request 请求参数 */
    private $request;

    /** @var OssConfig 天翼云OSS 配置 */
    private $config;

    public function __construct(Request $request, OssConfig $config)
    {
        $this->request = $request;
        $this->config  = $config;
    }

    public function sign()
    {
        $secretAccessKey = $this->config->getSecretAccessKey();
        $stringToSign    = $this->StringToSign($this->request);
        if ($this->config->debug) {
            VarDumper::dump('StringToSign: ' . $stringToSign);
        }
        $signature = base64_encode(hash_hmac('sha1', $stringToSign, $secretAccessKey, true));
        return 'AWS ' . $this->config->getAccessKeyId() . ':' . $signature;
    }

    /**
     * 组装待签字符串
     *
     * @param Request $request
     * @param string $bucket
     *
     * @return string
     */
    private function StringToSign(Request $request)
    {
        $stringToSign = $request->getMethod() . "\n";
        $stringToSign .= $request->getHeader('Content-MD5') . "\n";
        $stringToSign .= $request->getHeader('Content-Type') . "\n";
        $stringToSign .= $request->getDate()->toRfc7231String() . "\n";
        $stringToSign .= $this->CanonicalizedAmzHeaders($request->getXHeader());
        $stringToSign .= $this->CanonicalizedResource();

        return $stringToSign;
    }

    /**
     * 组装 x-amz 请求头待签字符串
     *
     * @param array $xHeader
     *
     * @return string
     */
    private function CanonicalizedAmzHeaders(array $xHeader)
    {
        if (empty($xHeader)) {
            return '';
        }

        $xAmz = '';
        foreach ($xHeader as $k => $v) {
            $xAmz .= $k . ':' . $v . "\n";
        }

        return $xAmz;
    }

    /**
     * 拼接访问资源待签字符串
     * @return string
     */
    private function CanonicalizedResource()
    {
        $bucket = $this->request->getBucket();
        if ($bucket === '') {
            return $this->request->getUrl();
        }

        return '/' . $bucket . $this->request->getUrl();
    }
}